<template>
    <div>
        <!-- 在u-image标签的外面套div，再给边距，否则无效，因为是一个UI组件 -->
        <div class="topImage" v-show="isShowResult === false">
            <!-- “/“开头的路径为绝对路径，表示从本项目的根目录开始 -->
            <u-image src="/static/hnlg_logo.png" mode="widthFix"></u-image>
        </div>

        <!-- gutter：元素之间的间距 -->
        <u-row gutter="10">
            <!-- span：占用的空间比例 -->
            <u-col span="9">
                <!-- 使用uView里面内置的上外边距class，值为20 -->
                <div class="u-margin-top-20">
                    <!-- change事件后面要跟着一个方法——inputListening()，记得加() -->
                    <u-search
                        placeholder="请输入题目关键字"
                        id="inputUrl"
                        v-model.trim="inputQuestion"
                        type="text"
                        :border="true"
                        border-color="#2979ff"
                        :clearable="true"
                        :show-action="false"
                        height="74"
                    ></u-search>
                </div>
            </u-col>
            <u-col span="3">
                <div class="u-margin-top-15"><u-button type="primary" @click="photoOcr">拍照识别</u-button></div>
            </u-col>
        </u-row>

        <!-- “加载中”的动画 -->
        <div class="loadingDiv" v-show="isLoading">
            <!-- “加载中”的动画 -->
            <u-loading mode="flower" textSize="30" size="50"></u-loading>
            <span class="loading">搜索中</span>
        </div>

        <u-index-list :scrollTop="0" :index-list="[]" v-if="isShowResult">
            <!-- 这里的div的属性不要换行，否则样式会出问题 -->
            <div class="questionList" v-for="content in searchResult" :key="content.id" @click="showAnswer(content)">
                <!-- 此组件用于显示内容，并且高亮显示标志出搜索的关键字 -->
                <search-highlight
                    ref="search"
                    @current-change="currentChange"
                    @mactch-count-change="matchCountChange"
                    :content="content.question"
                    :keyword="inputQuestion"
                ></search-highlight>
            </div>
        </u-index-list>

        <div class="emptyDiv" v-if="isShowEmpty"><u-empty text="搜不到此题目哦~" mode="search"></u-empty></div>

        <div class="completeTopicDiv" v-if="!isShowResult">
            <!-- 宫格布局（1列） -->
            <u-grid :col="1" class="completeTopic" :border="false">
                <!-- 使用v-for遍历数组（注意！:key绑定的不能是一个对象，而是具体的字符串等数据，否则会有警告） -->
                <u-grid-item :custom-style="{ padding: '10rpx 0 10rpx 0' }">
                    <p class="question">{{ completeTopic.question }}</p>
                    <div class="optionsDiv" v-for="options in completeTopic.options" :key="options">
                        <!--用于显示选项的正确与否，v-if如果判断出当前选项与答案一致，那么就展示打钩的图标，否则只是一个灰色的圈圈-->
                        <u-image
                            src="/static/correct.png"
                            mode="widthFix"
                            :width="80"
                            class="correctAndOptions"
                            v-if="options === completeTopic.answer"
                        ></u-image>
                        <!-- 且选项不为空时才显示，因为有些是简答题，简答题的答案会在下面的span中显示 -->
                        <u-image
                            src="/static/options.png"
                            mode="widthFix"
                            :width="80"
                            class="correctAndOptions"
                            v-if="options !== completeTopic.answer && options !== ''"
                        ></u-image>
                        <!-- 选项文字 -->
                        <span class="options">{{ options }}</span>
                        <span class="answer" v-if="options === ''">答案：{{ completeTopic.answer }}</span>
                    </div>
                </u-grid-item>
            </u-grid>
        </div>
    </div>
</template>

<script>
// 引入搜索高亮的组件
import SearchHighlight from "@/pages/index/search-highlight.vue";

// 引入子组件，路径要写完整，否则vite会报错
export default {
    components: {
        SearchHighlight
    },
    data() {
        return {
            // 我的服务器后端地址
            serverUrl: "https://thinkphp.hyy666.top/",
            // 是否正在加载
            isLoading: false,
            // 输入框中的内容，即题目关键字
            inputQuestion: "",
            // 是否正在搜索，用于决定查询结果、顶部华南理工大学图片的显示与隐藏
            isShowResult: false,
            // 是否允许搜索（用于节流机制，防止频繁修改搜素框的内容而导致频繁请求接口）
            isAllowSearch: null,
            // 查询的结果
            searchResult: [],
            // 是否展示“搜不到此题目哦~”的提示div
            isShowEmpty: false,
            // 完整的题目，包括题目、选项和答案
            completeTopic: [],
            // 是否显示完整的题目、选项、答案等信息
            showCompleteTopic: false,
            // 搜索高亮需要的变量
            currentIdx: 0,
            matchCount: 0
        };
    },
    watch: {
        // 监听是否输入了题目关键字，如果有输入（变化），就触发此方法
        inputQuestion() {
            // 开始加载
            this.isLoading = true;
            // 防抖机制，防止频繁修改搜素框的内容而导致频繁请求接口（设置为0.3秒）
            if (this.isAllowSearch) {
                clearTimeout(this.isAllowSearch);
            }
            this.isAllowSearch = setTimeout(() => {
                let inputQuestion = this.inputQuestion;
                // 加判断，当输入的内容不为空时，才向服务器请求
                if (inputQuestion) {
                    uni.request({
                        // 只要有发送数据，就是POST方法，而不是GET方法
                        method: "POST",
                        data: { inputContent: inputQuestion },
                        // 后台接口的url
                        url: `${this.serverUrl}SearchQuestions/getTopicInformation`,
                        success: res => {
                            // 提取出重要的内容
                            let result = res.data;
                            // 如果不为空数组，则证明有查询到内容
                            if (result.length !== 0) {
                                // 搜索得到就取消展示“搜不到此题目哦~”的提示div
                                this.isShowEmpty = false;
                                // 显示搜索结果
                                this.isShowResult = true;
                                // 将数组赋值给data中的数组
                                this.searchResult = result;
                            } else {
                                // 清空数组
                                this.searchResult = [];
                                // 展示“搜不到此题目哦~”的提示div
                                this.isShowEmpty = true;
                            }

                            // 加载完毕就关闭动画
                            this.isLoading = false;
                        },
                        fail: () => {
                            uni.showToast({
                                title: "服务器未开启",
                                // 使用icon:"none"，可以解除字数的限制，但会把图标隐藏掉
                                // image可以使用自定义的图片，作为提示
                                image: "/static/error.png"
                            });
                            // 关闭动画
                            this.isLoading = false;
                        }
                    });
                }

                // 判断输入长度
                if (this.inputQuestion.length > 0) {
                    // 当input中有内容时，下面的搜索列表显示出来
                    this.isShowResult = true;
                    // 在输入时隐藏题目
                    this.showCompleteTopic = false;
                } else if (this.inputQuestion.length === 0) {
                    // 关闭查询结果的显示
                    this.isShowResult = false;
                    // 清空数组（节约内存）
                    this.searchResult = [];
                    // 关闭“搜不到此题目哦~”的提示div
                    this.isShowEmpty = false;
                    // 关闭加载中的动画
                    this.isLoading = false;
                }
            }, 300);
        }
    },
    methods: {
        // 按下列表中的的题目后，显示答案
        showAnswer(content) {
            // 关闭查询结果的显示，同时也重新显示顶部图片
            this.isShowResult = false;
            // 清空数组
            this.searchResult = [];
            // 清空输入的内容
            this.inputQuestion = "";
            // 对数据进行格式化，将选项按空格分割成数组
            content.options = content.options.split(" ");
            // 将题目信息赋值给data中的变量
            this.completeTopic = content;
            // 显示完整的题目、选项、答案等信息
            this.showCompleteTopic = true;
        },
        // 图像文字识别
        photoOcr() {
            let imageBase64 = null;
            // 调用微信小程序拍照、选择相册的功能
            uni.chooseImage({
                count: 1,
                sizeType: ["original", "compressed"],
                // 这要注意，camera掉拍照，album是打开手机相册
                sourceType: ["camera", "album"],
                success: res => {
                    /*拍摄或选择照片完毕后，会自动缓存到一个缓存目录，这里能获取此照片的路径，因为图片有时不止一张，
                    所以格式默认为数组，但这里只取一张*/
                    this.showPhotoSrc = res.tempFilePaths[0];
                    // 如果选择完毕
                    if (res.errMsg === "chooseImage:ok") {
                        // 将“是否正在加载”改为true，开始执行“加载中”的动画
                        this.isLoading = true;
                        uni.getFileSystemManager().readFile({
                            filePath: this.showPhotoSrc,
                            // 编码格式为Base64，将图片转换为Base64编码的字符串
                            encoding: "base64",
                            success: res => {
                                // 将编码后的结果存储到局部变量中
                                imageBase64 = res.data;
                                uni.request({
                                    method: "post",
                                    // 将Base64编码传给后端
                                    data: { imageBase64: res.data },
                                    // 后台接口的url，接收Base64编码的图片字符串
                                    url: `${this.serverUrl}Image/cameraOcr`,
                                    success: res => {
                                        // 提取出重要的内容，即识别结果，并将里面每一个对象的“words”属性的值提取出来，组成一个新的数组
                                        // 并且只截取数组的前6个元素（0~6）
                                        let result = Array.from(res.data.words_result, ({ words }) => words).slice(
                                            0,
                                            6
                                        );
                                        if (result === []) {
                                            uni.showToast({
                                                title: "无法识别",
                                                // 使用icon:"none"，可以解除字数的限制，但会把图标隐藏掉
                                                // image可以使用自定义的图片，作为提示
                                                image: "/static/error.png"
                                            });
                                        } else {
                                            // 注意！这里一定要保留作用域，在下面的success方法里才能访问data变量
                                            let that = this;
                                            // 用户选择的结果
                                            let chooseResult = null;
                                            // 弹出菜单，让用户选择识别的结果
                                            uni.showActionSheet({
                                                itemList: result,
                                                success: function(res) {
                                                    // 将用户挑选的结果赋值给搜索框的值，自动搜素（res.tapIndex是选择选项的索引号）
                                                    // 这里不能直接使用this访问data中的变量，因为在其他的函数中，这里使用上面变量保存的作用域
                                                    that.inputQuestion = result[res.tapIndex].replace("()", "").trim();
                                                },
                                                fail: function(res) {
                                                    console.log(res.errMsg);
                                                }
                                            });
                                            uni.showToast({
                                                title: "识别成功",
                                                duration: 2000
                                            });
                                        }
                                        // 加载完毕就关闭动画
                                        this.isLoading = false;
                                    },
                                    fail: () => {
                                        uni.showToast({
                                            title: "服务器未开启",
                                            // 使用icon:"none"，可以解除字数的限制，但会把图标隐藏掉
                                            // image可以使用自定义的图片，作为提示
                                            image: "/static/error.png"
                                        });
                                        // 关闭动画
                                        this.isLoading = false;
                                    }
                                });
                            }
                        });
                    }
                }
            });
        },
        // 搜索高亮需要的方法
        searchNext() {
            this.$refs.search.searchNext();
        },
        searchLast() {
            this.$refs.search.searchLast();
        },
        matchCountChange(count) {
            this.matchCount = count;
        },
        currentChange(idx) {
            this.currentIdx = idx;
        },
        checkKeydown(event) {
            if (event.shiftKey) {
                this.searchLast();
            } else {
                this.searchNext();
            }
        }
    }
};
</script>

<style lang="scss" scoped>
// 顶部的华南理工大学图片
.topImage {
    margin-top: 20rpx;
}

/* 加载动画的div */
.loadingDiv {
    text-align: center;
}

/* “识别中”的文字 */
.loading {
    color: #909399;
}

// 查询出来的问题列表
.questionList {
    display: flex;
    box-sizing: border-box;
    width: 100%;
    padding: 10px 24rpx;
    overflow: hidden;
    color: #323233;
    font-size: 14px;
    line-height: 24px;
    background-color: #fff;
    // 下边框，作为分割线
    border-bottom: 1px #c8c9cc solid;
}

// 提示内容为空的div
.emptyDiv {
    margin-top: 200rpx;
}

// 包含完整题目的div
.completeTopicDiv {
    margin: 30rpx;
}

// 完整的题目、选项、答案等信息
.completeTopic {
    display: flex;
    justify-content: left;
}

// 题目
.question {
    width: 100%;
    text-align: left;
    font-size: 36rpx;
}

// 包含选项、图标的div
.optionsDiv {
    width: 100%;
    text-align: left;
    margin-top: 50rpx;
    // 让子元素垂直居中，父级设置为弹性布局且垂直居中
    display: flex;
    align-items: center;
}

// 打钩（正确）的图标
.correctAndOptions {
    margin-top: 8rpx;
    display: inline-block;
}

// 选项文字
.options {
    font-size: 34rpx;
    margin-left: 30rpx;
}

.answer {
    font-size: 34rpx;
}
</style>
